//全局函数定义，头文件调用
#include<stdio.h>
#include<stdlib.h>

/*
   




*/


//程序1
//课后作业6
void func(int b[][3]);

void func(int b[][3])
/*
   func函数中，func(int b[][3])定义了一个形式参数，形参大小就是指针的大小。
   这里和主函数a[3][4]所定义的宽度不同，在C语言中，这种写法是合法的，编译器会重新帮你进行排序,所以按照b[][3]的写法就是b[4][3]；
   不过这种写法在C++这种写法是不合格的，C++规定维度统一，在C++中，数组的维度信息在编译时需要被准确地确定，以确保类型安全
   也就是你调用形式参数和实际参数形式必须一样，将a[3][4]传参时，形式参数形式必须也是b[][4];

       b[4][3] = {
                   {1,2,3},
                   {4,5,6},
                   {7,8,9},
                   {10,11,12}
                 }
*/            
{
   printf("sizeof(b) = %d\n", sizeof(b));
   /*在函数 func(int b[][3]) 中，b 是一个二维数组的指针，具体来说，b 是一个指向包含3个整数的数组的指针。
   这里的 [] 实际上是一个省略号，表示数组的行数可以是任意的，但列数必须是固定的（这里是3）。
   因此，sizeof(b) 计算的是指针的大小，而不是整个二维数组的大小。
   在大多数现代系统上，指针的大小通常是4字节（32位系统）或8字节（64位系统）<我们现在电脑都是64位操作系统了>。
*/
   printf("%d\n", b[2][2]);
   
}

void test1()//我这里都是将int main替换成void test number形式，这样子你就很方便进行运行测试
{
   int a[3][4] = {
           {1, 2, 3, 4},
           {5, 6, 7, 8},
           {9, 10, 11, 12}
   };//在主函数里，定义了一个数组，这个数组int a[3][4]
   printf("sizeof(a) = %d\n", sizeof(a));
   func(a);//将主函数的实际参数传进func分支函数中，这个过程叫做传数组（传数组的首元素的地址，数组本质也是一个指针）
}

//程序2
//利用itoa到达将'整型数据'转化为'字符型'
void test2()
{
   int i;
   char a[33];

   printf("请输入一个数字:");
   scanf("%d", &i);

   itoa(i, a, 10);//itoa(待转化的整型数据,将转化的结果存储到字符数组中,指定转化的进制也就是转化成什么进制给字符数组a)
   /*
    itoa函数解析
    函数概要：
        itoa 函数将整型值转换为指定进制表示的标准字符串。
        如果是十进制数，并且数值为负，那么转换后的字符串前边有一个负号（'-'）；如果是其他进制数，其值始终被认为是无符号类型。
        用于存放的字符串必须拥有足够的空间，以便可以容纳任何可能的数值：对于 2 进制数，需要使用 (sizeof(int)*8+1) 个字节来存放。
        比如在 16 位平台上，需要 17 个字节来存放；在 32 位平台上，则需要 33 个字节来存放。

    注意：
        该函数并不是标准的 C 语言函数，所以不能在所有的编译器中使用。
        为了提高程序的可移植性，请使用 sprintf 函数代替。

    函数原型：
        #include <stdlib.h>
        ...
        char *itoa(int value, char *str, int base);

    参数解析：
        参数              含义
        value             待转换的整型数值
        str               用于存放转换结果的字符串
        base              1. 指定转换结果用多少进制数来表示;2. 取值范围是 2~36（2 表示二进制，10 表示十进制……）

    返回值(说人话就是函数输出结果)：
        返回值是一个指向转换结果的指针，同 str 参数。

    使用例子：
    #include <stdio.h>
    #include <stdlib.h>//包含了标准库函数的头文件，这里用来使用itoa函数

    int main()
    {
        int i;
        char buffer[33];

        printf("Enter a number: ");
        scanf("%d", &i);
        itoa(i, buffer, 10); //将i转换为十进制字符串。
        printf("decimal: %s\n", buffer);//输出十进制字符串
        itoa(i, buffer, 16);//将i转换为十六进制字符串。
        printf("hexadecimal: %s\n", buffer);//输出十六进制字符串
        itoa(i, buffer, 2);//将i转换为二进制字符串
        printf("binary: %s\n", buffer);//输出二进制字符串

        return 0;
    }

*/

   printf("输出结果为:%s\n", a);

  


}

//程序3
//类itoa实现将'整型数据'转化为'字符型'(初级版本:强制转化版本)
void test3()
{
   int a;

   printf("请输入一个数据:");
   scanf("%d", &a);

   printf("a = %d\n", a);
   printf("输出的结果为:%d\n", (char)a);
   //printf("输出的结果为:%c\n",(char)a);#这个不能使用%c,因为这个使用c的话是字符型,输出的结果需要经过ASCII码转化,例如将a = 64,以%c的形式输出的话，对应ASCII码就是：@

}

//程序4
//类实现itoa函数实现将'字符型'转化为'整型'(sprintf函数)
void test4()
{
   char buffer[256];

   int i;
   printf("输入一个参数:");
   scanf("%d", &i);

   sprintf(buffer," %d", i);
   //i 是一个整数值变量，它包含了你希望转换为字符串的整数。sprintf 函数的作用是将格式化的数据写入字符串中。具体来说，"%d" 是一个格式说明符，用于指定 i 是一个十进制整数。

   /*
   *   sprintf函数
       
       函数概要：
               与 printf 函数类似，不过 sprintf 函数是将格式化数据写入到字符串中。
               缓冲区的尺寸必须足够大，以至于可以包含整个转换后的结果。（snprintf 函数是更安全的版本）
               format 参数后边的额外参数数量由 format 决定，具体用法请参考 printf 函数中格式化占位符的解释。

       函数原型：
               #include <stdio.h>
               ...
               int sprintf(char *str, const char *format, ...);

       参数分析：
           参数                      含义
           str                       指向存放结果字符串的缓冲区（这是一个指向字符数组的指针，用于存储格式化后的字符串。该数组必须有足够的空间来容纳格式化后的字符串，包括字符串结束符 '\0'）
           format                    格式化字符串（这是一个格式控制字符串，它指定了后续参数的输出格式。格式控制字符串中可以包含普通字符和格式说明符，格式说明符以 % 开头，用于指定后续参数的类型和输出格式，例如 %d 用于整数，%f 用于浮点数等）
           ...                       可选参数,参考printf文档(也叫可变参数,可以传递零个或多个参数，这些参数将按照格式字符串中的说明进行格式化，并写入到 str 指向的字符数组中)
   
              
       格式化字符串：
           格式字符串 format 可以包含普通字符和格式说明符。格式说明符是以 % 开头，后面跟着一个或多个字符，用于指定如何格式化后续的参数
           例如:
           %d：用于格式化 int 类型的整数。
           %f：用于格式化 float 或 double 类型的浮点数。
           %s：用于格式化 char* 类型的字符串。
           %c：用于格式化单个字符 char。
           %x：用于格式化十六进制整数。
           %p：用于格式化指针地址。
           %u：用于格式化无符号整数
      
       注意事项：
          缓冲区溢出: 使用 sprintf 时需要注意目标缓冲区的大小，以避免缓冲区溢出。缓冲区溢出可能会导致程序崩溃或安全漏洞,说人话就是要在初始化字符数组的时候宽度设置大一点

      
   */

   
   printf("输出结果:%s", buffer);

}

//程序5
//类实现itoa函数实现将'字符数据'转为'整型'(snprintf函数)
void test5()
{
   char array[256];
   int i;
   printf("请输入一个字符：");
   scanf("%d", &i);

   snprintf(array, 10, "%d",i);
   /*
         snprintf函数

         函数概要：
                  snprintf 函数是 sprintf 函数的安全版本，因为它在调用的时候需要指定缓冲区的最大尺寸，这样可以有效避免缓冲区溢出。
                  如果写入的字符串尺寸大于 size - 1，那么后边的字符将被丢弃，但依旧会统计进长度中（返回值）。
                  format 参数后边的额外参数数量由 format 决定，具体用法请参考 printf 函数中格式化占位符的解释。
   
         函数原型：
                  #include <strdio.h>
                   ...
                   int snprintf(char *str, size_t size, const char *format, ...);

          参数解析：
                  参数                   含义
                  str                    指向存放结果字符串的缓冲区(指向用于存储格式化后字符串的字符数组的指针。)                          
                  size                   1.限定缓冲区最大可写入的字节数;2.字符串最多可以拥有 size - 1 个字符，最后一个空位用于存放 '\0'；3. size_t 被定义为无符号整型(指定 str 所指向数组的最大可写入字节数，包含字符串结束符 '\0'。如果格式化后的字符串长度超过 size - 1 个字符，多余的字符将被截断，并且会在字符串末尾添加 '\0'。)
                  format                 格式化字符串,用于指定输出的格式，其中可以包含普通字符和格式说明符（如 %d、%s、%f 等）
                  ...                    可变参数

         例子：
                   #include <stdio.h>
                   int main() {
                                   char buffer[20];
                                   int result;

                                   // 使用 snprintf 格式化字符串
                                   result = snprintf(buffer, sizeof(buffer), "The number is %d", 123);

                                   if (result >= 0) {
                                       if (result < sizeof(buffer)) {
                                           printf("Formatted string: %s\n", buffer);
                                       } else {
                                           printf("The string was truncated. Needed %d bytes.\n", result + 1);
                                       }
                                   } else {
                                       printf("An error occurred while formatting the string.\n");
                                   }

                                   return 0;
                               }

                   


   */
   printf("输出的结果是：%s", array);

}


//程序6
//类实现itoa函数实现将'字符串型'转化为'整型'<这个你肯定写过了，在编写这个的日期是2.24，这天你问了我这个158行代码含义>
void test6()
{
   int ch;
   int num = 0;
   printf("请输入一个整型数据:");
  
   do
   {
       ch = getchar();
       if (ch >= '0' && ch <= '9')
       {
           num = 10 * num + (ch - '0');
       }
       else
       {
           if (num)
           {
               break;
           }
       }

   } while (ch != '\n');
   printf("输出的结果是:%d",num);


}


//程序7
// 类实现itoa函数实现将'整型'转化为'字符型（小甲鱼课后作业0）

char* myitoa(int num, char* str);

char* myitoa(int num, char* str)
{
   int dec = 1;;//确定数字的位数，初始值为1.
   int i = 0;//用于跟踪字符串中的位置，初始值为0
   int temp;//用于存储num的临时值

   //判断用户输入的数据是否为负数
   if (num < 0)
   {
       str[i++] = '-';
       num = -num;
   }

   temp = num;//将num存储给temp
   
   //判断这个数据的位次，是个位还是千位
   while (temp > 9)
   {
       dec *= 10;
       temp /= 10;

   }

   //将while (dec != 0)，将整数num按照最高位到最低位逐个转换为字符，并存储到字符串str中
   while (dec != 0)
   {
       str[i++] = num / dec + '0';//通过整数除法num / dec得到当前位的数字，然后加上字符'0'的ASCII值，将数字转换为对应的字符
       num = num % dec;//通过取模运算num % dec去除已处理的最高位，以便处理下一位,说人话就是去除当前未位次，向下一位移动
       dec /= 10; //将dec除以10，移动到下一位的权值
   }

   str[i] = '\0';

   return 0;

}


void test7()
{
   char str[10];

   int a;
   printf("请输入一个数:");
   
   scanf("%d", &a);
   int result = myitoa(a, str);
   printf("返回的结果是：%s\n", str);
}






//主函数
int main()
{
   /*
       索引                  作用
       test1                 小甲鱼作业6，打印结果为9分析
       test2                 类实现itoa将用户输入的整型转化为字符串形式存储(省内存)
       test3                 类itoa实现将'整型数据'转化为'字符型'(初级版本:强制转化版本)
       test4                 类实现itoa函数实现将'字符型'转化为'整型'(sprintf函数)
       test5                 类实现itoa函数实现将'字符数据'转为'整型'(snprintf函数)
       test6                 类实现itoa函数实现将'字符串型'转化为'整型'
       test7                 类实现itoa函数实现将'整型'转化为'字符型（小甲鱼课后作业0）



   */


   test7();
   return 0;
}